"""扫描记录API"""
from typing import List, Optional, Dict, Any
from fastapi import APIRouter, Depends, HTTPException, status, Query, Body
from sqlalchemy.orm import Session
from datetime import datetime

from app.database import get_db
from app.services.scan_record_service import ScanRecordService
from app.services.scan_task_service import ScanTaskService
from app.schemas.scan_record import ScanRecordResponse
from app.schemas.common import ResponseBase, PaginatedResponse
from app.models.scan_record import ScanRecord
from app.utils.logger import logger

router = APIRouter()


@router.get("", response_model=PaginatedResponse[ScanRecordResponse])
async def get_scan_records(
    task_id: Optional[int] = Query(None, description="任务ID"),
    branch: Optional[str] = Query(None, description="分支名称"),
    status: Optional[str] = Query(None, description="状态"),
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
    order_by: Optional[str] = Query("scan_time desc", description="排序字段"),
    db: Session = Depends(get_db),
):
    """获取扫描记录列表"""
    service = ScanRecordService(db)

    # 构建过滤条件
    filters = {}
    if task_id:
        filters["task_id"] = task_id
    if branch:
        filters["branch"] = branch
    if status:
        filters["status"] = status

    records = service.get_all(
        skip=skip,
        limit=limit,
        filters=filters if filters else None,
        order_by=order_by,
    )
    total = service.count(filters=filters if filters else None)

    # 转换为响应格式
    record_responses = []
    for record in records:
        record_dict = ScanRecordResponse.from_orm(record).dict()
        # 添加任务名称
        if record.task:
            record_dict["task_name"] = record.task.name
        record_responses.append(ScanRecordResponse(**record_dict))

    return PaginatedResponse(
        code=200,
        message="success",
        data=record_responses,
        total=total,
        skip=skip,
        limit=limit,
    )


@router.get("/{record_id}", response_model=ResponseBase)
async def get_scan_record(
    record_id: int,
    db: Session = Depends(get_db),
):
    """获取扫描记录详情"""
    service = ScanRecordService(db)
    record = service.get_by_id(record_id)

    if not record:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"扫描记录 {record_id} 不存在",
        )

    record_dict = ScanRecordResponse.from_orm(record).dict()
    if record.task:
        record_dict["task_name"] = record.task.name

    return ResponseBase(
        code=200,
        message="success",
        data=ScanRecordResponse(**record_dict),
    )


@router.post("/scan/{task_id}", response_model=ResponseBase)
async def trigger_scan(
    task_id: int,
    branch: str = Body(..., description="扫描分支"),
    scan_params: Dict[str, Any] = Body(default={}, description="扫描参数"),
    created_by: Optional[str] = Body(None, description="创建人"),
    db: Session = Depends(get_db),
):
    """触发扫描任务"""
    from app.tasks.scan_tasks import scan_task
    from app.scanners.registry import ScanExecutorRegistry
    
    task_service = ScanTaskService(db)
    task = task_service.get_by_id(task_id)

    if not task:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"扫描任务 {task_id} 不存在",
        )
    
    if task.status != "enabled":
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"扫描任务 {task_id} 未启用",
        )
    
    # 检查执行器是否存在
    if not ScanExecutorRegistry.is_registered(task.task_type):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"任务类型 {task.task_type} 的执行器未注册",
        )
    
    # 创建扫描记录
    scan_record = ScanRecord(
        task_id=task_id,
        branch=branch,
        scan_time=datetime.now(),
        status="pending",
        scan_params=scan_params,
        created_by=created_by,
        issue_count=0,
        unconfirmed_count=0,
    )
    db.add(scan_record)
    db.commit()
    db.refresh(scan_record)
    
    # 提交Celery任务
    celery_task = scan_task.delay(
        scan_record_id=scan_record.id,
        task_id=task_id,
        task_type=task.task_type,
        branch=branch,
        scan_params=scan_params,
        created_by=created_by,
    )
    
    # 保存Celery任务ID到扫描参数中
    if scan_record.scan_params is None:
        scan_record.scan_params = {}
    scan_record.scan_params["celery_task_id"] = celery_task.id
    db.commit()
    
    return ResponseBase(
        code=200,
        message="扫描任务已提交",
        data={
            "scan_record_id": scan_record.id,
            "celery_task_id": celery_task.id,
            "status": "pending",
        },
    )


@router.get("/{record_id}/status", response_model=ResponseBase)
async def get_scan_status(
    record_id: int,
    db: Session = Depends(get_db),
):
    """获取扫描任务状态"""
    from celery.result import AsyncResult
    from app.celery_app import celery_app
    
    service = ScanRecordService(db)
    record = service.get_by_id(record_id)
    
    if not record:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"扫描记录 {record_id} 不存在",
        )
    
    # 尝试从扫描参数中获取Celery任务ID
    celery_task_id = None
    if record.scan_params and isinstance(record.scan_params, dict):
        celery_task_id = record.scan_params.get("celery_task_id")
    
    status_data = {
        "scan_record_id": record_id,
        "status": record.status,
        "issue_count": record.issue_count,
        "confirmed_count": record.confirmed_count,
        "unconfirmed_count": record.unconfirmed_count,
    }
    
    # 如果有Celery任务ID，查询任务状态
    if celery_task_id:
        try:
            task_result = AsyncResult(celery_task_id, app=celery_app)
            status_data["celery_task_id"] = celery_task_id
            status_data["celery_status"] = task_result.state  # PENDING, STARTED, SUCCESS, FAILURE, etc.
            
            if task_result.state == "SUCCESS":
                status_data["celery_result"] = task_result.result
            elif task_result.state == "FAILURE":
                status_data["celery_error"] = str(task_result.info)
        except Exception as e:
            logger.warning("Failed to get Celery task status", task_id=celery_task_id, error=str(e))
    
    return ResponseBase(
        code=200,
        message="success",
        data=status_data,
    )

